/**
 * 程序读取xml方式加载数据库连接配置文件
 * by @author lms 2024.10.09
 * 
 * maxStatements
 * Default: 0
 * The size of c3p0's global PreparedStatement cache. If both maxStatements and maxStatementsPerConnection are zero, 
 * statement caching will not be enabled. If maxStatements is zero but maxStatementsPerConnection is a non-zero value, 
 * statement caching will be enabled, but no global limit will be enforced, only the per-connection maximum. 
 * maxStatements controls the total number of Statements cached, for all Connections. If set, 
 * it should be a fairly large number, 
 * as each pooled Connection requires its own, distinct flock of cached statements. As a guide, 
 * consider how many distinct PreparedStatements are used frequently in your application, 
 * and multiply that number by maxPoolSize to arrive at an appropriate value. 
 * Though maxStatements is the JDBC standard parameter for controlling statement caching, 
 * users may find c3p0's alternative maxStatementsPerConnection more intuitive to use.
 * 
 * maxStatementsPerConnection
 * Default: 0
 * The number of PreparedStatements c3p0 will cache for a single pooled Connection. 
 * If both maxStatements and maxStatementsPerConnection are zero, statement caching will not be enabled. 
 * If maxStatementsPerConnection is zero but maxStatements is a non-zero value, statement caching will be enabled, 
 * and a global limit enforced, but otherwise no limit will be set on the number of cached statements for a single Connection. 
 * If set, maxStatementsPerConnection should be set to about the number distinct PreparedStatements that are used frequently in your application, 
 * plus two or three extra so infrequently statements don't force the more common cached statements to be culled. 
 * Though maxStatements is the JDBC standard parameter for controlling statement caching, 
 * users may find maxStatementsPerConnection more intuitive to use.
 */
package ms.core.db.mysql;

import java.io.InputStream;
import java.util.List;

import ms.core.tool.StreamTool;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import lombok.Data;
import ms.core.tool.Log4j2Tool;
import ms.core.tool.StrTool;

public class DbConfTool {
	//数据库类型
	public static enum DbType {dbUnknown, dbMySql, dbMsSql}

	/**
	 * MS-SQLServer数据库连接配置
	 * @author lms
	 */
	@Data
	public static class DbConf {
		private String jdbcUrl;
		private String driverClass;
		private String user;
        private String password;
        private int checkoutTimeout;
        private int idleConnectionTestPeriod;
        private int initialPoolSize;
        private int minPoolSize;
        private int maxPoolSize;
        private int maxIdleTime;
        private int maxStatements;				// c3p0全局PreparedStatement缓存的大小，默认值0。https://www.mchange.com/projects/c3p0/
        private int maxStatementsPerConnection;	// 单个连接允许缓存SQL最大数量，默认值0表示没有限制。https://www.mchange.com/projects/c3p0/

        public DbType getDbType() {
        	if (driverClass.contains("mysql"))
        		return DbType.dbMySql;
        	else if (driverClass.contains("sqlserver"))
        		return DbType.dbMsSql;
        	
        	return DbType.dbUnknown;
        }
	}

	/**
	 * 加载数据库连接配置
	 * 
	 * @param name (配置名称，如果名称为空或者null，取默认节点)
	 * @param fileName 配置文件名称
	 * @return
	 */
	public static DbConf loadConf(String name, String fileName) {
		DbConf ret = null;
        try {
            InputStream in = StreamTool.loadFileToStream(DbConfTool.class,fileName);
            SAXReader reader = new SAXReader();
            Document doc = reader.read(in);
            Element root = doc.getRootElement();
            List<Element> items = root.elements();
            for (Element item: items) {
            	// 获取配置节点名称
            	String confName = item.attributeValue("name");
            	if (!StrTool.equals(name, confName, true)) 
            		continue;

            	ret = new DbConf();
            	for (Element el: item.elements()) {
            		String propName  = el.attributeValue("name");
            		String propValue = el.getText();
            		// 获取属性值	
            		if (StrTool.equals("jdbcUrl", propName, true))
            			ret.setJdbcUrl(propValue);
            		else if (StrTool.equals("driverClass", propName, true))
            			ret.setDriverClass(propValue);
            		else if (StrTool.equals("user", propName, true))
            			ret.setUser(propValue);
            		else if (StrTool.equals("password", propName, true))
            			ret.setPassword(propValue);
            		else if (StrTool.equals("checkoutTimeout", propName, true))
            			ret.setCheckoutTimeout(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("idleConnectionTestPeriod", propName, true))
            			ret.setIdleConnectionTestPeriod(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("initialPoolSize", propName, true))
            			ret.setInitialPoolSize(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("minPoolSize", propName, true))
            			ret.setMinPoolSize(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("maxPoolSize", propName, true))
            			ret.setMaxPoolSize(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("maxIdleTime", propName, true))
            			ret.setMaxIdleTime(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("maxStatements", propName, true))
            			ret.setMaxStatements(StrTool.strToInt(propValue, 0));
            		else if (StrTool.equals("maxStatementsPerConnection", propName, true))
            			ret.setMaxStatementsPerConnection(StrTool.strToInt(propValue, 0));
            	}
            	break;
            }
            in.close();
        } catch (Exception e) {
            Log4j2Tool.error(DbConfTool.class, "parser c3p0.Xml:"+fileName, e);
        }
        return ret;
    }
}
